package com.yy.ptrdemo.library.utils;

import android.content.Context;
import android.content.res.TypedArray;
import com.yy.ptrdemo.library.loadinglayout.FlipLoadingLayout;
import com.yy.ptrdemo.library.loadinglayout.LoadingLayout;
import com.yy.ptrdemo.library.loadinglayout.RotateLoadingLayout;

/**
 * Created by Ayanami_Rei on 2014/9/2.
 *
 * Custom Enums
 */
public class CustomEnums {

    /**
     * The UI states
     */
    public static enum State {

        /**
         * When the UI is in a state which means that user is not interacting
         * with the pull_to_refreshing function
         */
        RESET(0x0),
        /**
         * When the UI is being pulled by user, but has not been pulled far
         * enough so that it can not refreshes when released
         */
        PULL_TO_REFRESH(0x1),
        /**
         * When the UI is being pulled by user, and has been pulled far enough
         * so that it will refresh when released
         */
        RELEASE_TO_REFRESH(0x2),
        /**
         * When the UI is currently refreshing, caused by a pull gesture
         */
        REFRESHING(0x8),
        /**
         * When the UI is currently refreshing, caused by a call to
         * {@link PullToRefreshBase#setRefreshing()}
         */
        MANUAL_REFRESHING(0x9),
        /**
         * When the UI is currently over scrolling, caused by a fling
         * on the Refreshable View
         */
        OVER_SCROLLING(0x10);

        /**
         * Maps an integer to a specific state. This is needed when saving state
         */
        public State mapValueToState(final int value) {

            for (State state : State.values()) {

                if (value == state.getStateValue()) {

                    return state;
                }
            }

            //default return RESET
            return RESET;
        }

        State(int stateValue) {

            this.mStateValue = stateValue;
        }

        public int getStateValue() {

            return this.mStateValue;
        }

        private int mStateValue;
    }

    /**
     * The determination of the relative position of user.
     */
    public static enum Orientation {

        VERTICAL,
        HORIZONTAL
    }

    public static enum AnimationStyle {

        /**
         * This is default animation style to pull to refresh.
         * Allows you to use any drawable, which is automatically rotated and use as progress bar.
         */
        ROTATE,
        /**
         * This animation style commonly used on ios.
         * Uses an arrow image which flips depends on where the user has scrolled.
         */
        FLIPS;

        /**
         * Maps an int to a specific mode .
         * This is needed when saving state or inflating the view from xml where the style is given through a attr int.
         *
         * @param styleValue int to map a style to.
         * @return Mode that styleValue maps to or ROTATE by default.
         */
        public static AnimationStyle mapValueToStyle(int styleValue) {

            switch (styleValue) {
                case 0x0:
                default:
                    return ROTATE;
                case 0x1:
                    return FLIPS;
            }
        }

        /**
         * @return Return default animation style.
         */
        public static AnimationStyle getDefaultStyle() {

            return ROTATE;
        }

        /**
         * Init a loading layout depends on style and return it.
         */
        public LoadingLayout createLoadingLayout(Context context, Mode mode,
                                                 Orientation scrollDirection, TypedArray attrs) {

            switch (this) {
                case ROTATE:
                default:
                    return new RotateLoadingLayout(context, mode, scrollDirection, attrs);
                case FLIPS:
                    return new FlipLoadingLayout(context, mode, scrollDirection, attrs);
            }
        }
    }

    public static enum Mode {

        /**
         * Disable all pull to refresh gesture and refreshing handing.
         */
        DISABLED(0x0),

        /**
         * Only allow the user to pull from the start of the refreshable view to refresh.
         * The start is either the top or left, depending on the scrolling direction.
         */
        PULL_FROM_START(0x1),

        /**
         * Only allow the user to pull from the end of the refreshable view to refresh.
         * The end is either the bottom or right, depending on the scrolling direction.
         */
        PULL_FROM_END(0x2),

        /**
         * Allow the user to pull from start, from end to refresh.
         */
        BOTH(0x3),

        /**
         * Disables pull to refresh gesture handing,
         * but allows manually setting the refreshing status.
         */
        MANUALLY_REFRESH_ONLY(0x4);

        //The mode need to match those from attrs.xml
        Mode(int modeValue) {

            this.mModeValue = modeValue;
        }

        /**
         * @return Return true if the mode permits pull to refresh.
         */
        public boolean isPermitsPullToRefresh() {

            return !(this == DISABLED || this == MANUALLY_REFRESH_ONLY);
        }

        /**
         * @return Return true if the mode wants the loading layout header to be shown.
         */
        public boolean isShowHeaderLoadingLayout() {

            return (this == PULL_FROM_START || this == BOTH);
        }

        /**
         * @return Return true if the mode wants the loading layout footer to be shown.
         */
        public boolean isShowFooterLoadingLayout() {

            return (this == PULL_FROM_END || this == BOTH || this == MANUALLY_REFRESH_ONLY);
        }

        /**
         * Maps an int to a specific mode.
         * This is needed when saving state, or inflating view from xml where the mode is given through a attr int.
         *
         * @param modeValue Int to map a mode to.
         * @return Mode that modeValue maps to or default.
         */
        public static Mode mapValueToMode(int modeValue) {

            for (Mode mode : Mode.values()) {

                if (modeValue == mode.getModeValue()) {

                    return mode;
                }
            }

            return getDefaultMode();
        }

        /**
         * @return Return current mode int value.
         */
        public int getModeValue() {

            return this.mModeValue;
        }

        /**
         * @return Return PULL_FROM_START by default.
         */
        public static Mode getDefaultMode() {

            return PULL_FROM_START;
        }

        private int mModeValue;
    }
}
